#include "VisibleObject.h"
#include "GameApp.h"

//------------------------------------------------------------------------------------
VisibleObject::VisibleObject(std::string actorID)
	: mpAnimator(0), mbDead(false)
{
	mpOgreInitData = OgreDataPtr(new OgreData());

	boost::shared_ptr<SettingsManager> sm(new SettingsManager(actorID));
	readVisibleObjectFromXML(sm);

	mTypes.push_front(OBJECT_VISIBLE);
}
//------------------------------------------------------------------------------------
VisibleObject::VisibleObject(std::string actorID, string name, btVector3 &pos, btQuaternion &rot, btVector3 &scale, string mesh)
	: mpAnimator(0), mbDead(false)
{
	mpOgreInitData = OgreDataPtr(new OgreData());

	boost::shared_ptr<SettingsManager> sm(new SettingsManager(actorID));
	readVisibleObjectFromXML(sm);

	mpOgreInitData->name = OStringPtr(new Ogre::String(name));
	mpOgreInitData->meshName = OStringPtr(new Ogre::String(mesh));
	mpOgreInitData->pos = cvt(pos);
	mpOgreInitData->scale = cvt(scale);

	mpOgreInitData->quat = cvt(rot);
	mpOgreInitData->pitch = 0.f;
	mpOgreInitData->yaw = 0.f;
	mpOgreInitData->roll = 0.f;

	mTypes.push_front(OBJECT_VISIBLE);
}
//------------------------------------------------------------------------------------
VisibleObject::VisibleObject(boost::shared_ptr<SettingsManager> sm)
	: mpAnimator(0), mbDead(false)
{
	mpOgreInitData = OgreDataPtr(new OgreData());

	readVisibleObjectFromXML(sm);

	mTypes.push_front(OBJECT_VISIBLE);
}
//------------------------------------------------------------------------------------
VisibleObject::VisibleObject(const OgreDataPtr data)
	: mpOgreInitData(data), mpAnimator(0), mbDead(false)
{
	mTypes.push_front(OBJECT_VISIBLE);
}
//------------------------------------------------------------------------------------
VisibleObject::VisibleObject(boost::shared_ptr<VisibleObject> ref)
	: mpAnimator(0), mbDead(false)
{
	OgreDataPtr data = ref->getOgreInitData();
	strstream s;
	s << *(data->name) << gpApp->mpGameLogic->nameCounter++;

	mpOgreInitData = OgreDataPtr(new OgreData());
	mpOgreInitData->name = OStringPtr(new Ogre::String(s.str()));
	mpOgreInitData->meshName = OStringPtr(new Ogre::String(*(data->meshName)));
	mpOgreInitData->pos = data->pos;
	mpOgreInitData->scale = data->scale;

	mpOgreInitData->quat = data->quat;
	mpOgreInitData->pitch = data->pitch;
	mpOgreInitData->yaw = data->yaw;
	mpOgreInitData->roll = data->roll;

	mpOgreInitData->visible = data->visible;

	mTypes.push_front(OBJECT_VISIBLE);

	// TODO: copy animator
}
//------------------------------------------------------------------------------------
VisibleObject::~VisibleObject(void)
{
	delete mpAnimator;

	//if (mpEntityNode) gpApp->mpView->removeObject(mpEntityNode);
}
//------------------------------------------------------------------------------------
void VisibleObject::readVisibleObjectFromXML(boost::shared_ptr<SettingsManager> sm)
{
	mpOgreInitData->name = OStringPtr(new Ogre::String(sm->getSetting("OgreData/Name/object").c_str()));
	mpOgreInitData->meshName = OStringPtr(new Ogre::String(sm->getSetting("OgreData/Name/mesh").c_str()));

	mpOgreInitData->pos = Ogre::Vector3(Ogre::Real(atof(sm->getSetting("OgreData/Position/x").c_str())),
										Ogre::Real(atof(sm->getSetting("OgreData/Position/y").c_str())),
										Ogre::Real(atof(sm->getSetting("OgreData/Position/z").c_str())));

	mpOgreInitData->scale = Ogre::Vector3(Ogre::Real(atof(sm->getSetting("OgreData/Scale/x").c_str())),
										  Ogre::Real(atof(sm->getSetting("OgreData/Scale/y").c_str())),
										  Ogre::Real(atof(sm->getSetting("OgreData/Scale/z").c_str())));

	mpOgreInitData->yaw = Ogre::Radian(Ogre::Real(atof(sm->getSetting("OgreData/Rotation/yaw").c_str())));
	mpOgreInitData->pitch = Ogre::Radian(Ogre::Real(atof(sm->getSetting("OgreData/Rotation/pitch").c_str())));
	mpOgreInitData->roll = Ogre::Radian(Ogre::Real(atof(sm->getSetting("OgreData/Rotation/roll").c_str())));
	mpOgreInitData->quat = Ogre::Quaternion::IDENTITY;
	mpOgreInitData->visible = atoi(sm->getSetting("OgreData/Properties/visible").c_str()) == 1;
}
//------------------------------------------------------------------------------------
void VisibleObject::setEntityNode(Ogre::SceneNode *node)
{
	mpEntityNode = node;
}
//------------------------------------------------------------------------------------
void VisibleObject::setAnimator(Animator* anim)
{
	mpAnimator = anim;
}
//------------------------------------------------------------------------------------
Ogre::SceneNode *VisibleObject::getEntityNode(void) const
{
	return mpEntityNode;
}
//------------------------------------------------------------------------------------
const OgreDataPtr VisibleObject::getOgreInitData(void) const
{
	return mpOgreInitData;
}
//------------------------------------------------------------------------------------
Ogre::Entity* VisibleObject::getEntity(void)
{
	return static_cast<Ogre::Entity*>(mpEntityNode->getAttachedObject(*(mpOgreInitData->name)));
}
//------------------------------------------------------------------------------------
void VisibleObject::update(const unsigned long elapsedTime)
{
	mpAnimator->stepAnimation(elapsedTime);
}
//------------------------------------------------------------------------------------
bool VisibleObject::dead(void) const
{
	return mbDead;
}
//------------------------------------------------------------------------------------
void VisibleObject::kill(void)
{
	mpAnimator->resetAnimations();
	if(!mbDead)gpApp->mpView->removeObject(mpEntityNode);
	mpEntityNode = 0;

	mbDead = true;
}
//------------------------------------------------------------------------------------
ObjectType VisibleObject::getType(void) const
{
	return mTypes.front();
}
//------------------------------------------------------------------------------------
bool VisibleObject::hasType(ObjectType type) const
{
	for(typeList::const_iterator it = mTypes.begin(); it != mTypes.end(); ++it)
	{
		if(*it == type) return true;
	}
	return false;
}
//------------------------------------------------------------------------------------
void VisibleObject::addType(ObjectType type)
{
	mTypes.push_front(type);
}
//------------------------------------------------------------------------------------
void VisibleObject::removeType(ObjectType type)
{
	mTypes.remove(type);
}
//------------------------------------------------------------------------------------
Animator* VisibleObject::getAnimator(void)
{
	return mpAnimator;
}